package com.zhengxing.jienci.user.service.rbac.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.CaseFormat;
import com.google.common.collect.Lists;
import com.zhengxing.jienci.user.domain.rbac.Role;
import com.zhengxing.jienci.common.util.IdGenerateUtil;
import com.zhengxing.jienci.user.mapper.rbac.RoleMapper;
import com.zhengxing.jienci.user.service.rbac.RoleResourceFuncService;
import com.zhengxing.jienci.user.service.rbac.RoleService;
import com.zhengxing.jienci.user.service.rbac.UserRoleService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * RoleServiceImpl
 *
 * @author philbert
 * @version 1.00
 */
@Slf4j
@Service
@Transactional
@Lazy
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    private static final String admin_role = "admin_role";

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RoleResourceFuncService roleResourceFuncService;
    @Autowired
    private UserRoleService userRoleService;

    /**
     * 保存角色
     *
     * @param role 角色
     * @return true=成功；false=失败
     */
    @Override
    public boolean save(Role role) {
        if (StringUtils.isBlank(role.getId())) role.setId(IdGenerateUtil.getId());
        if (role.getCreatedAt() == null) role.setCreatedAt(System.currentTimeMillis());
        return super.retBool(roleMapper.insert(role));
    }

    /**
     * 删除角色
     *
     * @param id 主键
     * @return true=成功；false=失败
     */
    @Override
    public boolean delete(String id) {
        userRoleService.deleteByRoleIds(Lists.newArrayList(id));
        roleResourceFuncService.deleteByRoleIds(Lists.newArrayList(id));
        boolean bool = super.retBool(roleMapper.deleteById(id));

        if (bool) {
//            List<UserRole> userRoles = userRoleService.findByRoleId(id);
//            userRoles.forEach(userRole -> userJdbcRealm.clearAuthorizationCache(userRole.getUserId())); // 清除shiro授权缓存
        }

        return bool;
    }

    /**
     * 更新角色
     *
     * @param role 角色
     * @return true=成功；false=失败
     */
    @Override
    public boolean update(Role role) {
        if (role.getCreatedAt() == null) role.setUpdatedAt(System.currentTimeMillis());
        boolean bool = super.retBool(roleMapper.updateById(role));

        if (bool) {
//            List<UserRole> userRoles = userRoleService.findByRoleId(role.getId());
//            userRoles.forEach(userRole -> userJdbcRealm.clearAuthorizationCache(userRole.getUserId())); // 清除shiro授权缓存
        }

        return bool;
    }

    /**
     * 查询角色
     *
     * @param id 主键
     * @return 角色
     */
    @Override
    @Transactional(readOnly = true)
    public Role get(String id) {
        return roleMapper.selectById(id);
    }

    /**
     * 查询角色分页对象
     *
     * @param paramMap 参数Map
     * @param orderBy  排序方式
     * @param pageNo   页码
     * @param pageSize 每页最大数量
     * @return 角色分页对象
     */
    @Override
    @Transactional(readOnly = true)
    public IPage<Role> getPagination(Map<String, Object> paramMap, String orderBy, int pageNo, int pageSize) {
        String name = MapUtils.getString(paramMap, "name");
        String code = MapUtils.getString(paramMap, "code");

        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(orderBy)) {
            String[] array = orderBy.split(" ");
            String format = "CONVERT(%s USING gbk)";
            String field = String.format(format, CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, array[0]));
            if (StringUtils.equalsIgnoreCase(array[1], "asc")) {
                queryWrapper.orderByAsc(field);
            } else if (StringUtils.equalsIgnoreCase(array[1], "desc")) {
                queryWrapper.orderByDesc(field);
            } else {
                throw new RuntimeException();
            }
        }
        LambdaQueryWrapper<Role> lambdaQueryWrapper = queryWrapper.lambda();
//        lambdaQueryWrapper.and(obj -> obj.ne(Role::getCode, admin_role));
        if (StringUtils.isNotBlank(name)) lambdaQueryWrapper.and(obj -> obj.like(Role::getName, name));
        if (StringUtils.isNotBlank(code)) lambdaQueryWrapper.and(obj -> obj.like(Role::getCode, code));

        Page<Role> page = new Page<>(pageNo, pageSize);

        return roleMapper.selectPage(page, queryWrapper);
    }

    /**
     * 查询名称是否已存在
     *
     * @param name     名称
     * @param excludId 要排除的记录主键
     * @return true=已存在；false=不存在
     */
    @Override
    @Transactional(readOnly = true)
    public boolean nameExist(String name, String excludId) {
        return roleMapper.nameExist(name, excludId) != null;
    }

    /**
     * 查询代码是否已存在
     *
     * @param code     代码
     * @param excludId 要排除的记录主键
     * @return true=已存在；false=不存在
     */
    @Override
    @Transactional(readOnly = true)
    public boolean codeExist(String code, String excludId) {
        return roleMapper.codeExist(code, excludId) != null;
    }

    /**
     * 查询所有角色
     *
     * @return 所有角色
     */
    @Override
    @Transactional(readOnly = true)
    public List<Role> findAll() {
        LambdaQueryWrapper<Role> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper.and(obj -> obj.ne(Role::getCode, admin_role));
        lambdaQueryWrapper.orderByAsc(Role::getName);
        return roleMapper.selectList(lambdaQueryWrapper);
    }

    /**
     * 根据名称查询角色
     *
     * @param name 名称
     * @return 角色
     */
    @Override
    @Transactional(readOnly = true)
    public Role getByName(String name) {
        LambdaQueryWrapper<Role> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Role::getName, name);
        return roleMapper.selectOne(lambdaQueryWrapper);
    }

}
